﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace TerenXNA
{
    //klasa kamera, po niej musza dziedziczyc wszystkie kamery
    //musza byc zaimplementowane wszystkie te funkcje
    //reszta co siedzi w srodku kamery - wszystko jedno
    public class Camera
    {
        public class Coords
        {
            // swiat kamery
            public World world;
            // wspolrzedne pola kamery w swiecie
            public int aktwx = 0, aktwy = 0, aktwz = 0;
            // wspolrzedne kamery na polu
            public float obx = 0, oby = 10, obz = 0;
            // kat patrzenia gracza
            public float kato = 0/*(float)3.14*/, katov = 0;
            // zakres widoczności kamery
            public float farValue = 35000.0f;
        }
        // polozenie kamery
        public Coords coords = new Coords();

        // czy kamera wczytana
        public bool loaded = false;
        
        // wlasciwosci kamery
        public int screenWidth = Convert.ToUInt16(System.Configuration.ConfigurationManager.AppSettings["ResolutionWidth"]);
        public int screenHeight = Convert.ToUInt16(System.Configuration.ConfigurationManager.AppSettings["ResolutionHeight"]);
        public float aspectRatio = (float)Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["ResolutionWidth"]) / (float)Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["ResolutionHeight"]); 

        public int starex, starey;
        public int scrollWheelValue = 0;
        //public bool updateHeight = true;

        //pauza poruszania kamery mysza w czasie wlaczonego menu
        public bool paused = false;

        public ScreenMenu.CameraType cameraType;

        public Camera(Coords coords)
        {
            this.coords = coords;
            starex = screenWidth / 2;
            starey = screenHeight / 2;
            loaded = true;
        }

        public Camera(World world)
        {
            coords.world = world;
            starex = screenWidth / 2;
            starey = screenHeight / 2;
            loaded = true;
        }

        public Camera()
        {
            starex = screenWidth / 2;
            starey = screenHeight / 2;
            loaded = true;
        }

        // funkcja obslugi zdarzen klawiatury
        public virtual void keyUpdate(KeyboardState keyboardState)
        {
            // zakres widocznosci zmieniany jest w menu
            /*
            if (keyboardState.IsKeyDown(Keys.Up))
            {
                coords.farValue += 200.0f;
                Console.WriteLine("farValue=" + coords.farValue);
            }
            if (keyboardState.IsKeyDown(Keys.Down))
            {
                coords.farValue -= 200.0f;
                if (coords.farValue < Game1.minFarValue)
                {
                    coords.farValue = Game1.minFarValue;
                }
                if (coords.farValue > Game1.maxFarValue)
                {
                    coords.farValue = Game1.maxFarValue;
                }
                Console.WriteLine("farValue=" + coords.farValue);
            }
            */
        }

        // funkcja obslugi zdarzen gapepada
        public virtual void buttonUpdate(GamePadState gamepadState)
        {
        }

        public void CameraPause()
        {
            this.paused = true;
            Game1.game1Ref.IsMouseVisible = true;
        }

        public void CameraResume()
        {
            this.paused = false;
            if (Game1.isMouseEnabled)
            {
                Game1.game1Ref.IsMouseVisible = false;
            }
        }


        // funkcja obslugi zdarzen muszki
        public virtual void mouseUpdate(MouseState mouseState)
        {
            // zakres widocznosci zmieniany jest w menu
            /*
            if (mouseState.ScrollWheelValue != scrollWheelValue)
            {
                coords.farValue += 10.0f * (mouseState.ScrollWheelValue - scrollWheelValue);
                if (coords.farValue < Game1.minFarValue)
                {
                    coords.farValue = Game1.minFarValue;
                }
                if (coords.farValue > Game1.maxFarValue)
                {
                    coords.farValue = Game1.maxFarValue;
                }
                Console.WriteLine("farValue=" + coords.farValue);
                scrollWheelValue = mouseState.ScrollWheelValue;
            }
            */
        }

        // funkcja sprawdzania kolizji z terenem
        public virtual void heightUpdate()
        {
        }

        // kolejne trzy funkcje zwracaja widok kamery
        // wiecej pod haslem CreateLookAt
        public virtual Vector3 getEye()
        {
            return new Vector3();
        }

        public virtual Vector3 getTarget()
        {
            return new Vector3();
        }

        public virtual Vector3 getUp()
        {
            return new Vector3();
        }

        // zwraca widok swiata, wiecej pod haslem
        // CreatePerspectiveFieldOfView
        public virtual Matrix view()
        {
            return new Matrix();
        }

        public virtual void viewUpdate()
        {

        }

        public static void switchCamera(int newCamera, ref Camera aktCam, MouseState mouseState) 
        {
            int currentScrollWheel = aktCam.scrollWheelValue;

            switch(newCamera)
            {
                case 0:
                    if (aktCam.cameraType != ScreenMenu.CameraType.Fly)
                        Console.WriteLine("Zmiana na tryb powietrzny.");
                    aktCam = new CameraFly(aktCam.coords);
                    if (Game1.isMouseEnabled)
                    {
                        Game1.game1Ref.IsMouseVisible = false;
                    }
                    break;

                case 1:
                    if (aktCam.cameraType != ScreenMenu.CameraType.Ground)
                        Console.WriteLine("Zmiana na tryb naziemny.");
                    aktCam = new CameraGround(aktCam.coords);
                    if (Game1.isMouseEnabled)
                    {
                        Game1.game1Ref.IsMouseVisible = false;
                    }
                    break;

                case 2:
                    if (aktCam.cameraType != ScreenMenu.CameraType.Debug)
                        Console.WriteLine("Zmiana na tryb testowania.");
                    aktCam = new CameraDebug(aktCam.coords);
                    if (Game1.isMouseEnabled)
                    {
                        Game1.game1Ref.IsMouseVisible = false;
                    }
                    break;

                case 3:
                    if (aktCam.cameraType != ScreenMenu.CameraType.Static)
                        Console.WriteLine("Zmiana na tryb nieruchomy.");
                    aktCam = new CameraStationary(aktCam.coords);
                    Game1.game1Ref.IsMouseVisible = true;
                    break;
            }

            aktCam.scrollWheelValue = currentScrollWheel;
            aktCam.starex = mouseState.X;
            aktCam.starey = mouseState.Y;
            aktCam.viewUpdate();
        }
    }
}
